/*
 * @Date         : 2022-06-08 09:53:04
 * @LastEditors  : zu1662
 * @LastEditTime : 2022-07-22 14:48:41
 * @Description  : 文件上传服务
 * 
 * Copyright © 2022 by zu1662, All Rights Reserved. 
 */
import { Injectable, InternalServerErrorException } from "@nestjs/common";
import { InjectRepository } from "@nestjs/typeorm";
import { Repository } from "typeorm";
import { FileEntity } from "./file.entity";
import { DebuggerService } from "src/debugger/service/debugger.service";
import { OssService } from "src/utils/oss/oss.service";
import { HelperDateService } from "src/utils/helper/service/helper.date.service";
import { HelperStringService } from "src/utils/helper/service/helper.string.service";
import { ENUM_STATUS_CODE_ERROR } from "src/utils/error/error.constant";
import { IFileListInfo } from "./file.interface";
@Injectable()
export class FileService {

  constructor(
    @InjectRepository(FileEntity)
    private readonly fileRepository: Repository<FileEntity>,
    private readonly ossService: OssService,
    private readonly helperStringService: HelperStringService,
    private readonly helperDateService: HelperDateService,
    private readonly debuggerService: DebuggerService,
  ) {}

  // 所有文件
  async findAll(queryParams: Record<string, any>):Promise<IFileListInfo> {
    const { skip, perPage, sort, availableSearch, search, filters } = queryParams
    
    const query = this.fileRepository.createQueryBuilder('file').orderBy(`file.${sort.field}`, sort.sortType);
    
    // 如果 search 存在，则模糊搜索，filters 为精确到字段搜索
    if(search && typeof search === 'string') {
      query.andWhere(`CONCAT(${availableSearch.join(',')}) LIKE "%${search}%"`)
    } else if (filters && typeof filters === 'object') {
      availableSearch.forEach(key => {
        if(filters[key]) {
          query.andWhere(`${key} LIKE :${key}`).setParameter(`${key}`, `%${filters[key]}%`);
        }
      })
    }
    
    const totalData = await query.getCount()
    query.skip(skip);
    query.take(perPage);
    return {
      totalData,
      data: await query.getMany()
    }
  }

  // 获取单个文件
  async findById(id: string): Promise<FileEntity> {
    return await this.fileRepository.findOne({where: { id }})
  }
  
  // 文件上传
 async uploadFile(file, unique: number | boolean): Promise<FileEntity> {
  const { originalname, mimetype, size, buffer } = file;
  const dateStr = this.helperDateService.format(new Date())
  const uuid: string = this.helperStringService.random(20);
  const filename = `/${dateStr}/${unique ? uuid + '/' : ''}${originalname}`
  let url = ''
  try {
    // 上传 alioss
    url = await this.ossService.putItemInBucket(filename, buffer)
  } catch (err) {
    this.debuggerService.error("File upload to oss", "FileController", "upload", err);
    throw new InternalServerErrorException({
      statusCode: ENUM_STATUS_CODE_ERROR.UNKNOWN_ERROR,
      message: "http.serverError.internalServerError",
    });
  }
  // 文件实体信息
  const fileEntity = {
    originalname,
    filename,
    url,
    type: mimetype,
    size,
  }
  const newFile = await this.fileRepository.create(fileEntity);
  await this.fileRepository.save(newFile);
  return newFile
 }

 // 文件删除
 async deleteById(id: string): Promise<void> {
  const target = await this.fileRepository.findOne({ where: { id }});
  try {
    // alioss 删除
    await this.ossService.deleteItemInBucket(target.filename)
  } catch (err) {
    this.debuggerService.error("File delete from alioss", "FileController", "delete", err);
    throw new InternalServerErrorException({
      statusCode: ENUM_STATUS_CODE_ERROR.UNKNOWN_ERROR,
      message: "http.serverError.internalServerError",
    });
  }
  await this.fileRepository.remove(target);
 }
}
